package com.sjax.myapp.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import com.sjax.myapp.json.Criterion;
import com.sjax.myapp.json.Criterion.CompareCriterion;
import com.sjax.myapp.json.Criterion.CompareType;

/**
 * jqGrid的Utils类.
 * 
 * @author liukai
 * 
 */
public class JqGridUtils {

	/**
	 * 把接收到的filter通过jackson解析为对象并装入一个List中.
	 * 
	 * @param filters
	 *            JqGrid进行多条件查询时自带的参数.
	 * @return
	 */
	public static List<Criterion> generateSearchCriteriaFromFilters(
			String filters) {

		List<Criterion> criteria = new ArrayList<Criterion>();

		ObjectMapper mapper = new ObjectMapper();

		try {
			// 通过jackson 把filters里的数据装入JsonNode中.
			JsonNode rootNode = mapper.readValue(filters, JsonNode.class);

			// 去处JsonNode中"rules"的数据
			JsonNode rulesNode = rootNode.path("rules");

			// 去处字符串里的双引号.
			String groupOp = StringUtils.replace(rootNode.path("groupOp")
					.toString(), "\"", "");

			for (int i = 0; i < rulesNode.findValues("field").size(); i++) {

				// 获得需要查询的字段
				String field = StringUtils.replace(rulesNode
						.findValues("field").get(i).toString(), "\"", "");

				// 获得输入的查询字段
				String data = StringUtils.replace(rulesNode.findValues("data")
						.get(i).toString(), "\"", "");

				// 获得jqgrid的操作符号,如op,eq,cn等.
				String op = StringUtils.replace(
						rulesNode.findValues("op").get(i).toString(), "\"", "");

				Criterion criterion = generateSearchCriterion(groupOp, field,
						data, op);

				if (criterion != null) {
					criteria.add(criterion);
				}
			}

		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return criteria;
	}

	/**
	 * 通过一下3个参数生成一个对象 ,该方法也可适用于单条件查询.
	 * 
	 * @param groupOp
	 *            jqgrid自带参数:匹配规则.有2个参数:AND , OR.
	 * @param searchField
	 *            jqgrid自带参数:查询字段
	 * @param searchString
	 *            jqgrid自带参数:输入的查询字段
	 * @param searchOper
	 *            jqgrid自带参数:操作符号.如op,eq,cn,bw等.
	 * @return
	 */
	public static Criterion generateSearchCriterion(String groupOp,
			String searchField, String searchString, String searchOper) {
		Criterion criterion = null;
		if (StringUtils.isNotEmpty(searchString)
				&& StringUtils.isNotEmpty(searchOper)
				&& StringUtils.isNotEmpty(searchField)) {

			if ("eq".equals(searchOper)) {
				// 等于
				criterion = Criterion.getEqualCriterion(groupOp, searchField,
						searchString);
			} else if ("ne".equals(searchOper)) {
				// 不等于
				criterion = Criterion.getCompareCriterion(groupOp,
						CompareType.NE, searchField, searchString);
			} else if ("lt".equals(searchOper)) {
				// 小于
				criterion = Criterion.getCompareCriterion(groupOp,
						CompareType.LT, searchField, searchString);
			} else if ("le".equals(searchOper)) {
				// 小于等于
				criterion = Criterion.getCompareCriterion(groupOp,
						CompareType.LTE, searchField, searchString);
			} else if ("gt".equals(searchOper)) {
				// 大于
				criterion = Criterion.getCompareCriterion(groupOp,
						CompareType.GT, searchField, searchString);
			} else if ("ge".equals(searchOper)) {
				// 大于等于
				criterion = Criterion.getCompareCriterion(groupOp,
						CompareType.GTE, searchField, searchString);
			} else if ("bw".equals(searchOper)) {
				// 开始于 :以*开头
				criterion = Criterion.getLikeCriterion(groupOp, searchField,
						searchString + "%");
			} else if ("bn".equals(searchOper)) {
				// 不开始于:不以*开头
				criterion = Criterion.getNotLikeCriterion(groupOp, searchField,
						searchString + "%");
			} else if ("ew".equals(searchOper)) {
				// 结束于:以*结尾
				criterion = Criterion.getLikeCriterion(groupOp, searchField,
						"%" + searchString);
			} else if ("en".equals(searchOper)) {
				// 不结束于:不以*结尾
				criterion = Criterion.getNotLikeCriterion(groupOp, searchField,
						"%" + searchString);
			} else if ("cn".equals(searchOper)) {
				// 包含
				criterion = Criterion.getLikeCriterion(groupOp, searchField,
						"%" + searchString + "%");
			} else if ("nc".equals(searchOper)) {
				// 不包含
				criterion = Criterion.getNotLikeCriterion(groupOp, searchField,
						"%" + searchString + "%");
			}

		}
		return criterion;

	}

	/**
	 * 根据tableName判断是否需要加".",如果为null和"",返回""
	 */
	public static String getFieldPrefix(String tableName) {
		return StringUtils.isEmpty(tableName.trim()) ? "" : tableName + ".";
	}

	/**
	 * 将Criteria转换为SQL条件语句
	 * 
	 * @param criteria
	 *            JSON解析出来的数据放入的对象
	 * @param tableName
	 *            查询语句后跟的表名,可以为null. ex:select * from User where tableName.id =
	 *            ?.
	 * @return 返回一个sql语句
	 */
	public static String converToSql(List<Criterion> criteria, String tableName) {

		String criteriaString = "";

		StringBuilder sb = new StringBuilder();
		sb.append(" where ");
		String prefix = getFieldPrefix(tableName);
		for (Criterion criterion : criteria) {

			String groupOp = criterion.getGroupOp() + " ";

			switch (criterion.getCriterionType()) {
			case EQUAL:
				sb.append(prefix + criterion.getField() + " = ?  " + groupOp);
				break;
			case LIKE:
				sb.append(prefix + criterion.getField() + " like ?  " + groupOp);
				break;
			case NOT_LIKE:
				sb.append(prefix + criterion.getField() + " not like ?  "
						+ groupOp);
				break;
			case COMPARE:
				CompareType compareType = ((CompareCriterion) criterion)
						.getCompareType();
				switch (compareType) {
				case EQ:
					sb.append(prefix + criterion.getField() + " = ? " + groupOp);
					break;
				case NE:
					sb.append(prefix + criterion.getField() + " <> ? "
							+ groupOp);
					break;
				case GT:
					sb.append(prefix + criterion.getField() + " > ? " + groupOp);
					break;

				case GTE:
					sb.append(prefix + criterion.getField() + " >= ? "
							+ groupOp);
					break;

				case LT:
					sb.append(prefix + criterion.getField() + " < ? " + groupOp);
					break;
				case LTE:
					sb.append(prefix + criterion.getField() + " <= ? "
							+ groupOp);
					break;
				}
				break;
			}
		}
		int i = -1;
		if ((i = sb.lastIndexOf("AND")) != -1
				|| (i = sb.lastIndexOf("OR")) != -1) {
			criteriaString = sb.substring(0, i);
		}
		return criteriaString;
	}

	/**
	 * 将Criteria各条件的值转换为List<Object>
	 * 
	 * @param criteria
	 * @return
	 */
	public static List<Object> getCriteriaValues(List<Criterion> criteria) {

		List<Object> criteriaValues = criteria.isEmpty() ? Collections
				.emptyList() : new ArrayList<Object>();

		for (Criterion criterion : criteria) {
			criteriaValues.add(criterion.getValue());
		}
		return criteriaValues;
	}

}
